package com.wangbo.rabbit;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Configuration
public class RabbitConfig {
    @Resource
    public RabbitTemplate rabbitTemplate;

    /**
     * 定义一个死信交换机
     */
    @Bean
    public DirectExchange DLXExchange() {
        return new DirectExchange(Constant.DLX_EXCHANGE_NAME);
    }

    /**
     * 定义一个死信队列
     */
    @Bean
    public Queue DLXQueue() {
        return new Queue(Constant.DLX_QUEUE_NAME, true, false, false);
    }

    /**
     * 绑定死信队列和交换机
     */
    @Bean
    public Binding DLXBinding() {
        return BindingBuilder.bind(DLXQueue()).to(DLXExchange()).with(Constant.DLX_ROUTING_KEY);
    }

    /**
     * 定义一个交换机，类型 Direct，名为 myDirectExchange, visual-host 中没有则创建
     */
    @Bean
    public DirectExchange myDirectExchange() {
        // 默认持久化，默认不自动删除
        return new DirectExchange(Constant.DIRECT_EXCHANGE_NAME);
    }

    /**
     * 定义一个队列，名为 myDirectQueue，visual-host 中没有则创建
     */
    @Bean
    public Queue myDirectQueue() {
        // 默认持久化，默认共享，默认不自动删除
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-message-ttl", 10000); // 设置队列的过期时间：10s
        arguments.put("x-max-length", 10000); // 设置队列消息最大容量。当队列已满，新消息直接进死信队列。
        arguments.put("x-dead-letter-exchange", Constant.DLX_EXCHANGE_NAME); // 设置队列的死信交换机。
        arguments.put("x-dead-letter-routing-key", Constant.DLX_ROUTING_KEY); // 设置队列的死信路由key。
        return new Queue(Constant.DIRECT_QUEUE_NAME, true, false, false, arguments);
    }

    /**
     * 把队列绑定到交换机上，routingKey 为 waves，visual-host 中没有则创建
     */
    @Bean
    public Binding myDirectBinding() {
        return BindingBuilder.bind(myDirectQueue()).to(myDirectExchange()).with(Constant.DIRECT_ROUTING_KEY);
    }

    /**
     * 定制 rabbitTemplate, 设置发送确认
     */
    @Bean
    public RabbitTemplate rabbitTemplate() {
        // 设置开启Mandatory,才能触发回调函数,无论消息推送结果怎么样都强制调用回调函数
        rabbitTemplate.setMandatory(true);

        // producer -> exchange 确认回调
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback(){
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("ConfirmCallback:     "+"相关数据："+correlationData);
                System.out.println("ConfirmCallback:     "+"确认情况："+ack);
                System.out.println("ConfirmCallback:     "+"原因："+cause);
            }
        });

        // exchange -> queue 消息退回回调
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback(){
            @Override
            public void returnedMessage(ReturnedMessage returned) {
                System.out.println("ReturnCallback:     " + "消息：" + returned.getMessage());
                System.out.println("ReturnCallback:     " + "回应码：" + returned.getReplyCode());
                System.out.println("ReturnCallback:     " + "回应信息：" + returned.getReplyText());
                System.out.println("ReturnCallback:     " + "交换机：" + returned.getExchange());
                System.out.println("ReturnCallback:     " + "路由键：" + returned.getRoutingKey());
            }
        });

        return rabbitTemplate;
    }

}
